angular.module('starter.services', ['starter.config'])

	.factory('APP', function($q, $ionicPopup, $filter){
		var self = this;
		var min_precision = 4000;
		self.user_id= 0;
		self.name= "AlturaRunning";
		
		self.convertMiliToTime= function(_mili){
			var _seconds = _mili / 1000;
			var aux= "";
			
			var _hours = parseInt(_seconds / 3600);
			_seconds = _seconds % 3600;
			if( _hours < 10)
				aux= "0";
			aux+= _hours+":";
			
			var _minutes = parseInt(_seconds / 60);
			_seconds = parseInt(_seconds%60);	
			if( _minutes < 10)	
				aux+="0";
			aux+= _minutes+":";
			
			if( _seconds  < 10 )
				aux+="0";
			aux+= _seconds;
			
			return aux;
		};
		
		self.convertMsToKmh= function(ms){
			if(!ms)
				return 0.0;
			
			var aux = ms * 3.6;
			return aux.toFixed(2);
			//return aux;
		};
		
		self.calculatePace= function(speed, returnMili) {
			var _minutes;
			var _seconds;
			var aux = "";
			if( speed > 0){
				_minutes = parseInt((1000/speed)/60);
				_seconds = parseInt((1000/speed)%60);
				
				if(returnMili !== 'undefined' && returnMili)
					return (_minutes * 60000) + (_seconds * 1000);
					
				if( _minutes > 99){
					aux = "00:00";
					return aux;
				}
				
				if(	_minutes < 10)
					aux = "0";
				aux += _minutes +":";
				
				
				if( _seconds < 10)
					aux+="0";
				aux+= _seconds;
			}
			else {
				if(returnMili !== 'undefined' && returnMili)
					aux= 0;
				else
					aux = "00:00";
			}
			return  aux;	
		};
		
		self.mediaVelocity= function(_duration, _distance) {
			var aux;
			
			if((_distance == 0) || (_duration == 0))
				return 0;
			return ((_distance*1000)/(_duration/1000))
			/*var total=0;
			for(i=0; i < index; i++)
				total+= coords[i].coords.speed;
			if( total )
				return total/index;
			return 0;*/
		};
		
		self.showAlert = function(message) {
			 var alertPopup = $ionicPopup.alert({
			   title: self.name,
			   template: $filter('translate')(message)
			 });
			 alertPopup.then(function(res) {
			   //console.log('Thank you for not eating my delicious ice cream cone');
			 });
	   };
		
		self.calculateScore= function(distance, duration, age){
			var records = [];
			var i, index, percent, prevision_time;
			var bonus, score;
			var aux = {};
			aux.km = 5;
			aux.time	= 840; // 14 min
			aux.age = 30;
			records.push(aux);
			
			var aux = {};			
			aux.km = 10;
			aux.time = 1740; // 29 min
			aux.age = 30;
			records.push(aux);
			
			var aux = {};			
			aux.km = 21.975;
			aux.time = 3600; // 1 hora
			aux.age = 30;	
			records.push(aux);
			
			var aux = {};			
			aux.km = 42.195;
			aux.time = 7620; // 2 horas e 7 minutos
			aux.age = 30;		
			records.push(aux);
			
			index= 0;
			for(i=0; i < 4; i++){
				if( distance < records[i].km){
					index = i;
					break;
				}
			}
					
			prevision_time = (duration/1000) * Math.pow((records[index].km/distance), 1.07);
			percent = records[index].time * 100 / prevision_time;
			bonus = 0;
			
			if( age > records[index].age)
				bonus = age - records[index].age;
			
			score = percent * 10 + bonus;
			
			if( score < 20 )
				score = 20 + bonus;
				
			if( score > 1000)
				score = 1000;
			
			return score.toFixed(2);
		}
		
		return self;
	})

	
	.factory('DB', function($q, DB_CONFIG, APP) {
		var self = this;
		self.db = null;
		self.production = true;
		
		self.init = function() {
			// Use 
			//if( self.production)
				//self.db = window.sqlitePlugin.openDatabase({name: DB_CONFIG.name}); //in production
			//else
				//self.db = window.openDatabase(DB_CONFIG.name, '1.0', 'database', -1);
	 
			//self.query('DROP TABLE IF EXISTS data_exerc');
			//var sql = 'INSERT INTO data_exerc (exerc_id, d_time, lat, lon, hrm, alt, heading, speed, accuracy) '+
			//	      'VALUES(1413713991340,3000,-17.302323,40.932032,100, 732, 0, 2, 3)';
			//self.query(sql);
	 
			/*angular.forEach(DB_CONFIG.tables, function(table) {
				var columns = [];
	 
				angular.forEach(table.columns, function(column) {
					columns.push(column.name + ' ' + column.type);
				});
	 
				var query = 'CREATE TABLE IF NOT EXISTS ' + table.name + ' (' + columns.join(',') + ')';
				self.query(query);
				//console.log('Table ' + table.name + ' initialized');
			});
			
			//var query = 'INSERT INTO exercises (name, person_id) VALUES ("teste", 1)';
			//self.query(query);*/
		};
	 
		self.query = function(query, bindings) {
			bindings = typeof bindings !== 'undefined' ? bindings : [];
			var deferred = $q.defer();
	 
			self.db.transaction(function(transaction) {
				transaction.executeSql(query, bindings, function(transaction, result) {
					deferred.resolve(result);
				}, function(transaction, error) {
					//console.log(error.message);
					APP.showAlert(error.message);
					deferred.reject(error);
				});
			});
	 
			return deferred.promise;
		};
	 
		self.fetchAll = function(result) {
			var output = [];
	 
			for (var i = 0; i < result.rows.length; i++) {
				output.push(result.rows.item(i));
			}
			
			return output;
		};
	 
		self.fetch = function(result) {
			return result.rows.item(0);
		};
	 
		self.getNumberRows= function(result){
			return result.rows.length;
		}
		
		return self;
	})


	.factory('ExerciseService', function($http, DB, APP, HeartRateService){
		var self = this;
		var min_precision = 45;
		var index = 0;
		var counter= 0;
		var name= "Teste";
		var exercise_type = 1;
		var is_indoor= false;
		var coords = new Array();
		var watchID;
		var timer;
		var startDate;
		var startTime;
		var endDate;
		var endTime;
		var totalDistance =0;
		var messageDistance= 1000; //A cada quantos metros será dado uma mensagem
		var messageDistanceAux=0; 
		var messageSeconds= 20;
		var messageSecondsAux=0;
		var isToShowMessageDistance= false;
		var isToShowMessageTime= true;
		var lastPosition;
		var lastSpeed = 0;
		var R = 6371; // km 
		var started = false;
		var minAccuracy= 4000;
		var map;
		var infowindow;
		var pace;
		var _id;
		var calories;
		var kms; //Estatisticas de cada km: velocidade, hrm, elevacao, pace, total_time
		var estatistics = new Array();
		var speed_km;
		var hrm_km;
		var distance_km;
		var time_km;
		var counter_km;
		var counter_media_km;
		var max_speed_km;
		var max_speed_total;
		var ascent_km;
		var descent_km;
		var ascent_total;
		var descent_total;
		var speed_total;
		var hrm_total;	
		var max_hr;
		var searching_gps;
		var accuracy;
      var hr;
      var dif;
      var useHrm;
		//var details, statistics;

		
		self.all = function() {
			var sql = "SELECT id, name, strftime('%d/%m/%Y',datetime(ex_date_time/1000, 'unixepoch')) AS ex_date_time, "+
					  "strftime('%H:%M:%S',datetime(duration/1000,'unixepoch')) AS duration, "+
					  "strftime('%M:%S', datetime(pace/1000,'unixepoch')) AS pace, "+
					  "elevation_gain, round(distance, 2) AS distance, round(speed * 3.6, 2) AS speed, "+
					  "calories, round(score) AS score, cadence, ex_date_time AS ordered "+
			          "FROM exercises "+
					  "WHERE person_id = ? "+
					  "ORDER BY ordered DESC";	
			return DB.query(sql,[APP.user_id])
			.then(function(result){
				return DB.fetchAll(result);
			});
		};
		
		self.getById = function(id, all_fields) {
			bindings = typeof bindings !== 'undefined' ? bindings : [];
			all_fields = typeof all_fields !== 'undefined' ? all_fields : false;
			
			//console.log("id: "+id+"  --- user_id: "+APP.user_id);
			
			var sql = "";
			if( all_fields)
				sql = "SELECT * ";
			else 
				sql = "SELECT id, name, strftime('%d/%m/%Y',datetime(ex_date_time/1000, 'unixepoch')) AS ex_date_time, "+
					  "strftime('%H:%M:%S', datetime(ex_date_time/1000, 'unixepoch')) AS init_time, strftime('%H:%M:%S', datetime(duration/1000,'unixepoch')) AS duration, "+
					  "strftime('%M:%S', datetime(pace/1000,'unixepoch')) AS pace, "+
					  "elevation_gain, round(distance, 2) AS distance, round(speed * 3.6, 2) AS speed, "+
					  "calories, round(score) AS score, cadence, img_route, avg_hr, max_hr ";
					  
			sql+= "FROM exercises "+
				  "WHERE id = ? AND person_id = ?";
			return DB.query(sql, [id, APP.user_id])
			.then(function(result){
				return DB.fetch(result);
			});
		};

		self.deleteExercise = function(id){
			var sql = "DELETE FROM data_exerc WHERE exerc_id = "+id;
			DB.query(sql);

			var sql = "DELETE FROM statistics WHERE exerc_id = "+id;
			DB.query(sql);			
		
			var sql = "DELETE FROM exercises WHERE id = "+id;
			DB.query(sql);
		};
		
		self.render = function() {			
			//$("#spinner").show();
			var config = JSON.parse(localStorage.getItem("config"));
			if( config !== null){
				//console.log(JSON.stringify(config));
				
				isToShowMessageDistance= config.showMessageDistance;
				isToShowMessageTime= config.showMessageTime;
				messageDistance= config.messageDistance;
				messageSeconds= config.messageSeconds;
				name = config.exercise_name;
				exercise_type = config.exerciseType;
				is_indoor = config.isIndoor;
			}
			else{
				isToShowMessageDistance= false;
				isToShowMessageTime= false;
				name = "Corrida";
				exercise_type = 1;
				is_indoor = false;			
			}
			//TEMP
			isToShowMessageDistance= false;
			isToShowMessageTime= false;

         useHrm = JSON.parse(localStorage.getItem("useHrm"));
         useHrm = useHrm == null ? false : useHrm;         
		};
		
		self.searchGps= function(){
			searching_gps = true;
			watchID = navigator.geolocation.watchPosition(onMove, onError, {enableHighAccuracy:true});
		}
		
		self.stopSearchGps= function(){
			navigator.geolocation.clearWatch(watchID);
		}
		
		self.isSearchingGps= function(){
			return searching_gps;
		}
		
      self.isStarted= function(){
         return started;
      }
      
		self.getAccuracy= function(){
			return accuracy;
		}
		
      self.searchHeartRate= function(){
         HeartRateService.init();
      }
      
		self.start = function() {
			if(!started){
				APP.showAlert('starting_exercise');
				
				totalDistance=0;
				messageDistanceAux= 0;
				messageSecondsAux=0;
				index=0;
				startDate= new Date();
				startTime = startDate.toLocaleTimeString();
				time_km = startDate.getTime();
				lastPosition= 0;
				distance_km=0;
				speed_km=0;
				hrm_km=0;
				counter_km=0;
				counter_media_km=0;
				max_speed_km=0;
				max_speed_total=0;
				ascent_km=0;
				descent_km=0;
				ascent_total= 0;
				descent_total= 0;
				speed_total=0;
				hrm_total=0;
				max_hr= 0;
				started= true;
				
				timer = setInterval(function (){refresh()}, 1000);
			}
		};		
		
		self.stop = function() {
			if(started){
				APP.showAlert('finished_exercise');
				navigator.geolocation.clearWatch(watchID);
				started = false;
				clearInterval(timer);
				
				//pega as estatisticas que ainda não foram guardadas
				putStatistics(true);
				
				storeData();			
			}
		};	
		
		self._export = function(exercise, details, statistics){

			var my_url = "http://alturarunning.zz.mu/get.php";
			//var my_url = "http://alturarunning.bugs3.com/get.php";
			//var my_url = "http://localhost/alturaRunningSite/get.php";
		
			var aux= [];
			exercise.tam = details.length;
			exercise.tam_estatistics = statistics.length;
			aux.push(exercise);
			aux.push(details);
			aux.push(statistics);
			
			$http.post(my_url, aux).
			  success(function(data, status, headers, config) {
				// this callback will be called asynchronously
				// when the response is available
				index = data.indexOf('img');
				end = data.lastIndexOf('.png');
				img = data.substring(index + 6, end+4);
				
				var sql = "UPDATE exercises SET img_route = '"+img+"', exported = 'true' WHERE id = "+exercise.id;
				DB.query(sql);
				APP.showAlert("upload_sucess");
			  }).
			  error(function(data, status, headers, config) {
				// called asynchronously if an error occurs
				// or server returns response with an error status.
				APP.showAlert("upload_error");
			  });
		}
		
		localJsonpCallback= function(json) {

		};				
			
		refresh = function() {
			endDate = new Date();
			endTime= endDate.toLocaleTimeString();
			
			var milessims = endDate.getTime() - startDate.getTime();
			$('#div_time').html(APP.convertMiliToTime(milessims));
			
			//TODO: calcular calorias 
			calories = parseInt(milessims/4000);
			$('#div_calories').html(calories);
			
			//TODO:Melhorar código, não esta mostrando as mensagens no momento correto
			if( isToShowMessageTime){
				messageSecondsAux++;
				if( messageSecondsAux >= messageSeconds ){
					//não atrasar a proxima mensagem
					messageSecondsAux=parseInt(messageSecondsAux-messageSeconds);
					navigator.vibrate(1000);
					new talk().time(APP.convertMiliToTime(milessims));
					//showMessage();
				}
			}
		};		
		
		onMove = function(position) {
			//TODO: temp
			accuracy = position.coords.accuracy.toFixed(1);
			$('#div_accuracy').html(accuracy);
			
			
			//Atualiza o progressbar
			//if( accuracy < 100)
				//$('progressbar').style.width= parseInt(100 - accuracy) +'%';
			//else
				//$('progressbar').style.width = "20%";
			
			if (!started) {
				if (position.coords.accuracy < minAccuracy){
					minAccuracy= position.coords.accuracy;
					//moveInfoWindow(position);
				}
				
				if(searching_gps && (accuracy < min_precision) && (accuracy > 0)){
					//$("#spinner").hide();
					searching_gps= false;
				}				
				return;
			}
			
			if(position.coords.accuracy < min_precision)
			{
         
            position.coords.hr = 0;
            
            if( useHrm ){            
               hr = HeartRateService.getLastHr();
               //console.log("Move: "+hr.bpm+" bpm - "+hr.time);
               //Se o bpm for recebido nos ultimos 5 segundos
               dif= Math.abs(endDate.getTime() - hr.time.getTime());
               
               if( dif < 5000)
                  position.coords.hr = hr.bpm;
               //TODO: falar mensagem de hrm perdido
            }   
            
            //console.log("Dif: "+dif+" hrm: "+position.coords.hr+" hrm real: "+hr.bpm);
            
				speed_total+= position.coords.speed;
				hrm_total+= position.coords.hr;		
				speed_km += position.coords.speed;
				hrm_km += position.coords.hr;
				counter_media_km++;
				
				if( position.coords.speed > max_speed_km)
					max_speed_km= position.coords.speed;
					
				if( position.coords.speed > max_speed_total)
					max_speed_total= position.coords.speed;
				
				//Pode ser isso que esta causando o erro				
				if( position.coords.hr > max_hr)	
					max_hr= position.coords.hr;
					
				if(lastPosition != 0) {
					var _distance= distanceCoordenades(lastPosition.coords.latitude, lastPosition.coords.longitude,
												  position.coords.latitude, position.coords.longitude);
					totalDistance+= _distance;
					
					//Ascent
					/*if( position.coords.altitude > lastPosition.coords.altitude){
						//ascent_km+= position.coords.altitude - lastPosition.coords.altitude;
						//ascent_total+= position.coords.altitude - lastPosition.coords.altitude;
					}
					else{ //Descent
						//descent_km+= lastPosition.coords.altitude - position.coords.altitude;
						//descent_total+= lastPosition.coords.altitude - position.coords.altitude;
					}*/
					
					//Store data for estatistics per km
					distance_km+= _distance;

					if( distance_km >= 1.0){
						putStatistics(false);
						distance_km= distance_km - 1.0;
						counter_media_km=0;
						time_km= endDate.getTime();
						speed_km=0;
						hrm_km=0;
						max_speed_km=0;
						ascent_km = 0;
						descent_km = 0;
						
						navigator.vibrate(1000);
					}
					
					//Show message per distance
					if( isToShowMessageDistance){
						messageDistanceAux+= _distance;
						if( messageDistanceAux >= messageDistance){
							messageDistanceAux=(messageDistanceAux-messageDistance);
							showMessage();
						}
					}
					var _media = position.coords.speed; //mediaLastVelocity();
					
					//Atual avg pace calculate
					pace= APP.calculatePace(_media);
					$('#div_pace').html(pace);
			
					$('#div_speed').html(APP.convertMsToKmh(_media)+ " Km/h");
					$('#div_distance').html(totalDistance.toFixed(2) +" Km's");
				}
				lastPosition = position;
				coords[index++]= position;
				//$('#div_hrm').html(index);
			}
		};
		
		putStatistics= function(calculateKm){
			kms= new Array();
			
			if( (hrm_km != 0) && (counter_media_km!=0))
				kms.hrm= hrm_km/counter_media_km;
			else
				kms.hrm= 0;
				
			kms.total_time= endDate.getTime() - startDate.getTime();
			kms.time = endDate.getTime() - time_km;
			
			if(calculateKm){
				kms.km = totalDistance.toFixed(2);
				kms.speed = APP.mediaVelocity(kms.time, (totalDistance - parseInt(totalDistance)));
			}
			else {	
				kms.km = counter_km + 1;		
				kms.speed = APP.mediaVelocity(kms.time, 1)
			}
			kms.max_speed = max_speed_km;
			kms.ascent = ascent_km;
			kms.descent = descent_km;
			
			estatistics[counter_km++]= kms;	
		};
	
		onError = function(error) {
			if( error.code == 1)
				APP.showAlert('permission_denied');
			else if( error.code == 2)
				APP.showAlert('network_error');
			else
				APP.showAlert('code: ' + error.code + '\n' + 'message: '+ error.message + '\n');
		};
		
		Number.prototype.toRad = function() {
			return this * Math.PI / 180;
		};

		toRad = function(n) {
			return n * Math.PI / 180;
		};		
		
		//Calcula distância entre duas coordenadas atraves da fórmula de Haversine
		distanceCoordenades= function(lat1, lon1, lat2, lon2) {
			var x1, x2;
			var dLat, dLon;
			var a, c, d=0.0;

			x1 = lat2-lat1;
			dLat = toRad(x1);  
			x2 = lon2-lon1;
			dLon = toRad(x2);  
			a = Math.sin(dLat/2) * Math.sin(dLat/2) + 
				Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * 
				Math.sin(dLon/2) * Math.sin(dLon/2);  
			c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
			d = R * c;			
			
			return d;
		};		
		
		//TODO: melhorar código. lastSpeed está errado
		mediaLastVelocity = function() {
			if(lastPosition == 0)
				return 0.0;
			var mediaSpeed=0;
			mediaSpeed= (lastSpeed + lastPosition.coords.speed) / 2;
			lastSpeed = lastPosition.coords.speed;
			
			return mediaSpeed;
		};
		
		storeData= function(){
			//Timestamp for the id
			var hash = new Date().getTime();
			var duration= (endDate.getTime() - startDate.getTime()); //Duration in seconds
			_media= APP.mediaVelocity(duration, totalDistance);
			pace = APP.calculatePace(_media, true);
			var score = APP.calculateScore(totalDistance, duration, 30);
			var elevation_gain= ascent_total - descent_total;
			var avg_hr = 0;
         
			//Calculate calories
			var peso = 80.0;
			if( exercise_type == 1)
				calories = (_media*3.6) * peso  * 0.0175 * (duration/60000);
			else if( exercise_type == 2){
				calories = (_media*3.6) * peso  * 0.0175 * (duration/60000);
			}
			else
				calories = (_media*3.6) * peso  * 0.0175 * (duration/60000);
				
         if(hrm_total > 0)
            avg_hr= hrm_total / index;
            
			//TODO: inserir aclive e declive
			var sql= 'INSERT INTO exercises (id, name, ex_date_time, type_id, person_id, '+
											'duration, distance, calories, speed, avg_hr, '+
											'pace, is_indoor, max_speed, last_change, exported, '+
											'max_hr, score, cadence, elevation_gain, description) '+
					' VALUES ('+hash
							+',"'+name
							+'",'+startDate.getTime()
							+','+exercise_type
							+','+APP.user_id
							+','+duration
							+','+totalDistance
							+','+calories
							+','+_media
							+','+avg_hr
							+','+pace
							+',"'+is_indoor
							+'",'+max_speed_total
							+','+hash
							+', "false"'
							+','+max_hr
							+','+score
							+',0,'
							+elevation_gain+',"")';
			
			//console.log(sql);
			DB.query(sql);
			
			sql = 'INSERT INTO data_exerc (exerc_id, d_time, lat, lon, hrm, alt, heading, speed, accuracy) VALUES ';
			var rest = false;
			for(i=0; i < index; i++){
				rest= true;
				sql+= ' ('+hash+',"'
						+coords[i].timestamp+'","'
						+coords[i].coords.latitude+'","'
						+coords[i].coords.longitude +'","'
						+coords[i].coords.hr+'","'
						+coords[i].coords.altitude+'","'
						+coords[i].coords.heading+'","'
						+coords[i].coords.speed+'","'
						+coords[i].coords.accuracy+ '")';					
					
				if( i % 400 == 0){
					rest = false;
					sql+=';';
					DB.query(sql);
					sql = 'INSERT INTO data_exerc (exerc_id, d_time, lat, lon, hrm, alt, heading, speed, accuracy) VALUES ';
				} else if( i < index - 1){
					sql+=', ';
				}
					
			}			
			
			if( rest){
				sql+=';';
				DB.query(sql);
			}
	
			//Store statistics
			for(i=0; i < counter_km; i++){
				//var elevation_gain = estatistics[i].ascent - estatistics[i].descent;
				sql= 'INSERT INTO statistics (exerc_id, km, total_time, d_time, hrm, speed, max_speed) '+ //, ascent, descent, elevation_gain
					 'VALUES ('+hash
						+','+estatistics[i].km
						+','+estatistics[i].total_time
						+','+estatistics[i].time
						+','+estatistics[i].hrm
						+','+estatistics[i].speed
						+','+estatistics[i].max_speed
						//+','+estatistics[i].ascent
						//+','+estatistics[i].descent
						//+','+elevation_gain
						+')';
				//console.log(sql);
				DB.query(sql);
			}
		};		
		
		return self;
	})

	
	.factory('StatisticsService', function(DB, APP){
		var self = this;
		
		self.getByExerciseId = function(id, all_fields){
			all_fields = typeof all_fields !== 'undefined' ? all_fields : false;
			
			var sql = "";
			if( all_fields)
				sql= "SELECT * ";
			else
				sql = "SELECT id, km, strftime('%H:%M:%S', datetime(total_time/1000, 'unixepoch')) AS total_time,"+
                  "strftime('%M:%S', datetime(d_time/1000, 'unixepoch')) AS d_time, round(speed*3.6, 2) AS speed, "+
                  "round(hrm) AS hrm ";
					  
			
			sql+="FROM statistics WHERE exerc_id = ?";
			
			//console.log(sql);
			return DB.query(sql, [id])
			.then(function(result){
				return DB.fetchAll(result);
			});
		};		
		return self;
	})

	
	.factory('ExerciseDetailsService', function(DB, APP){
		var self = this;
		
		self.getByExerciseId = function(id, all_fields){
			all_fields = typeof all_fields !== 'undefined' ? all_fields : false;
			
			var sql = "";
			if( all_fields)
				sql= "SELECT * ";
			else
				sql = "SELECT * ";
					  
			sql+="FROM data_exerc WHERE exerc_id = ?";
			
			//console.log(sql);
			return DB.query(sql, [id])
			.then(function(result){
				return DB.fetchAll(result);
			});
		};		
		
		self.count = function(id){
			var sql = "SELECT COUNT(*) AS total FROM data_exerc WHERE exerc_id = ?";
			
			return DB.query(sql, [id])
			.then(function(result){
				return DB.fetch(result);
			});
		};
		
		return self;
	})	
	
	
	.factory('ResumeService', function(DB, APP){
		var self = this;
		
		self.getLastExercise = function(){
			var sql = "SELECT strftime('%d/%m/%Y',datetime(ex_date_time/1000, 'unixepoch')) AS ex_date_time, "+
					  "strftime('%H:%M:%S',datetime(duration/1000,'unixepoch')) AS duration, round(distance, 2) AS distance , "+
					  "round(speed*3.6,2) AS speed, round(score) AS score, ex_date_time AS ordered  "+
					  "FROM exercises "+
					  "WHERE person_id = ? "+
					  "ORDER BY ordered DESC "+
					  "LIMIT 1";
			
			//console.log(APP.user_id);
			return DB.query(sql, [APP.user_id])
			.then(function(result){
				return DB.fetch(result);
			});			
		};
		
		self.getLastWeek = function(){
			var date_tmp = new Date();
			//get the date without time
			var date = new Date(date_tmp.getFullYear(), date_tmp.getMonth(), date_tmp.getDate());
			var milliseconds = date.getTime();
			var seven_days = 604800000;
			
			milliseconds-= seven_days;
	
			var sql = "SELECT strftime('%H:%M:%S',datetime(SUM(duration/1000),'unixepoch')) AS duration, "+
					  "round(SUM(distance),2) AS distance, "+
					  "round(AVG(speed*3.6),2) AS speed, round(SUM(calories)) AS calories, "+
					  "COUNT(*) AS quant "+
					  "FROM exercises "+
					  "WHERE person_id = ? "+
					  "AND ex_date_time >= "+milliseconds;
			
			//console.log(sql);
			return DB.query(sql, [APP.user_id])
			.then(function(result){
				return DB.fetch(result);
			});					
		};
		
		self.getLastMonth = function(){
			var date_tmp = new Date();
			//get the date without time
			var date = new Date(date_tmp.getFullYear(), date_tmp.getMonth(), date_tmp.getDate());
			var milliseconds = date.getTime();
			var month = 30 * 24 * 60 * 60 * 1000;
			
			milliseconds-= month;
	
			var sql = "SELECT strftime('%H:%M:%S',datetime(SUM(duration/1000),'unixepoch')) AS duration, "+
					  "round(SUM(distance),2) AS distance, "+
					  "round(AVG(speed*3.6),2) AS speed, round(SUM(calories)) AS calories, "+
					  "COUNT(*) AS quant "+
					  "FROM exercises "+
					  "WHERE person_id = ? "+
					  "AND ex_date_time >= "+milliseconds;
			
			return DB.query(sql, [APP.user_id])
			.then(function(result){
				return DB.fetch(result);
			});					
		};
		
		return self;
	})
	
	
	.service('CordovaService', function($location, DB, APP) {
		document.addEventListener("deviceready", function() {
			DB.init();
			
			var data = JSON.parse(localStorage.getItem("person"));
			
			//console.log(JSON.stringify(data));
			if( (data !== null) && (data[0]['message'] == 'success')){
				APP.user_id = data[0]['user_id'];
			}
			else
			{
				//$scope.user_id = 0;
				APP.user_id = 0;		
			}			
			
			$location.path('/app/resume');
		}, false);
	})
	
	
	.service('HeartRateService', function(APP){
      var self = this;
      var bluetoothle = window.bluetoothle;
		var addressKey = "address";

		var heartRateServiceUuid = "180d";
		var heartRateMeasurementCharacteristicUuid = "2a37";
		var clientCharacteristicConfigDescriptorUuid = "2902";
		var batteryServiceUuid = "180f";
		var batteryLevelCharacteristicUuid = "2a19";

		var scanTimer = null;
		var connectTimer = null;
		var reconnectTimer = null;

		var iOSPlatform = "iOS";
		var androidPlatform = "Android";
      var address;
      var hr= {};
		

      self.init = function(){
         var paramsObj = {request:true};
         
         hr.bpm = 0;
         hr.time = new Date();         
         
         bluetoothle.initialize(initializeSuccess, initializeError, paramsObj);
      }
      
      self.getLastHr= function(){
         return hr;
      }
      
		initializeSuccess= function(obj)
		{
         if (obj.status == "enabled")
         {
            bluetoothle.enable(enableSuccess, enableError);
            address = window.localStorage.getItem(addressKey);
            if (address == null)
            {
               console.log("Bluetooth initialized successfully, starting scan for heart rate devices");
               var paramsObj = {"serviceUuids":[heartRateServiceUuid]};
               bluetoothle.startScan(startScanSuccess, startScanError, paramsObj);
            }
            else
            {
               connectDevice(address);
            }
		  }
		  else
		  {
			console.log("Unexpected initialize status: " + obj.status);
		  }
		}

		initializeError= function(obj)
		{
		  console.log("Initialize error: " + obj.error + " - " + obj.message);
		}

      enableSuccess= function(obj)
      {
         console.log("Enable Success : " + JSON.stringify(obj));
         
        if (obj.status == "enabled")
        {
         console.log("Enabled");
        }
        else
        {
         console.log("Unexpected Enable Status");
        }
      }

      enableError= function(obj)
      {
        console.log("Enable Error : " + JSON.stringify(obj));
      }
      
      
		startScanSuccess= function(obj)
		{
		  if (obj.status == "scanResult")
		  {
			console.log("Stopping scan..");
			bluetoothle.stopScan(stopScanSuccess, stopScanError);
			clearScanTimeout();

			window.localStorage.setItem(addressKey, obj.address);
         address = obj.address;
				connectDevice(obj.address);
		  }
		  else if (obj.status == "scanStarted")
		  {
			console.log("Scan was started successfully, stopping in 10");
			scanTimer = setTimeout(scanTimeout, 10000);
		  }
		  else
		  {
			console.log("Unexpected start scan status: " + obj.status);
		  }
		}

		startScanError= function(obj)
		{
		  console.log("Start scan error: " + obj.error + " - " + obj.message);
		}

		scanTimeout= function()
		{
		  console.log("Scanning time out, stopping");
		  bluetoothle.stopScan(stopScanSuccess, stopScanError);
		}

		clearScanTimeout= function()
		{ 
			console.log("Clearing scanning timeout");
		  if (scanTimer != null)
		  {
			clearTimeout(scanTimer);
		  }
		}

		stopScanSuccess= function(obj)
		{
		  if (obj.status == "scanStopped")
		  {
			console.log("Scan was stopped successfully");
		  }
		  else
		  {
			console.log("Unexpected stop scan status: " + obj.status);
		  }
		}

		stopScanError= function(obj)
		{
		  console.log("Stop scan error: " + obj.error + " - " + obj.message);
		}

		connectDevice= function(address)
		{
         console.log("Begining connection to: " + address + " with 10 second timeout");
			var paramsObj = {"address":address};
         bluetoothle.connect(connectSuccess, connectError, paramsObj);
         connectTimer = setTimeout(connectTimeout, 10000);
		}

		connectSuccess= function(obj)
		{
		  if (obj.status == "connected")
		  {
			console.log("Connected to : " + obj.name + " - " + obj.address);
         
			clearConnectTimeout();
         var paramsObj = {"address":address};
         console.log("Beginning discovery :" + JSON.stringify(paramsObj));
         bluetoothle.discover(discoverSuccess, discoverError, paramsObj);
		  }
		  else if (obj.status == "connecting")
		  {
			console.log("Connecting to : " + obj.name + " - " + obj.address);
		  }
			else
		  {
			console.log("Unexpected connect status: " + obj.status);
			clearConnectTimeout();
		  }
		}

		connectError= function(obj)
		{
		  console.log("Connect error: " + obj.error + " - " + obj.message);
		  clearConnectTimeout();
		}

		connectTimeout= function()
		{
		  console.log("Connection timed out");
		}

		clearConnectTimeout= function()
		{ 
			console.log("Clearing connect timeout");
		  if (connectTimer != null)
		  {
			clearTimeout(connectTimer);
		  }
		}

		tempDisconnectDevice= function(address)
		{
         var paramsObj = {"address":address};
		  console.log("Disconnecting from device to test reconnect");
			bluetoothle.disconnect(tempDisconnectSuccess, tempDisconnectError, paramsObj);
		}

		tempDisconnectSuccess= function(obj)
		{
			if (obj.status == "disconnected")
			{
				console.log("Temp disconnect device and reconnecting in 1 second. Instantly reconnecting can cause issues");
				setTimeout(function(){reconnect();}, 1000);
			}
			else if (obj.status == "disconnecting")
			{
				console.log("Temp disconnecting device");
			}
			else
		  {
			console.log("Unexpected temp disconnect status: " + obj.status);
		  }
		}

		tempDisconnectError= function(obj)
		{
		  console.log("Temp disconnect error: " + obj.error + " - " + obj.message);
		}

		reconnect= function()
		{
         var paramsObj = {"address":address};
         console.log("Reconnecting with 5 second timeout "+ JSON.stringify(paramsObj));
         bluetoothle.reconnect(reconnectSuccess, reconnectError, paramsObj);
         reconnectTimer = setTimeout(reconnectTimeout, 5000);
		}

		reconnectSuccess= function(obj)
		{
         if (obj.status == "connected")
         {
            var paramsObj = {"address":obj.address};
            console.log("Reconnected to : " + obj.name + " - " + obj.address);

            clearReconnectTimeout();

            if (1 == 2)//(window.device.platform == iOSPlatform)
            {
               console.log("Discovering heart rate service");
               var paramsObj = {"serviceUuids":[heartRateServiceUuid]};
               bluetoothle.services(servicesHeartSuccess, servicesHeartError, paramsObj);
            }
            else //if (window.device.platform == androidPlatform)
            {
            
               var paramsObj = {"address":address,"serviceUuid":heartRateServiceUuid, "characteristicUuid":heartRateMeasurementCharacteristicUuid};
               console.log("Discovery completed" + JSON.stringify(paramsObj));
               bluetoothle.subscribe(subscribeSuccess, subscribeError, paramsObj);
               //setTimeout(unsubscribeDevice, 5000);                     
            }
		  }
		  else if (obj.status == "connecting")
		  {
			console.log("Reconnecting to : " + obj.name + " - " + obj.address);
		  }
		  else
		  {
			console.log("Unexpected reconnect status: " + obj.status);
			disconnectDevice();
		  }
		}

		discoverSuccess= function(obj)
		{
			if (obj.status == "discovered")
			{
				tempDisconnectDevice(address);
			//readBatteryLevel();
		  }
		  else
		  {
			console.log("Unexpected discover status: " + obj.status);
			disconnectDevice();
		  }
		}

		discoverError= function(obj)
		{
		  console.log("Discover Error : " + JSON.stringify(obj));
		  //disconnectDevice(address);
		}      
      
		reconnectError= function(obj)
		{
		  console.log("Reconnect error: " + obj.error + " - " + obj.message);
		  disconnectDevice();
		}

		reconnectTimeout= function()
		{
		  console.log("Reconnection timed out");
		}

		clearReconnectTimeout= function()
		{ 
			console.log("Clearing reconnect timeout");
		  if (reconnectTimer != null)
		  {
			clearTimeout(reconnectTimer);
		  }
		}

		servicesHeartSuccess= function(obj)
		{
		  if (obj.status == "discoveredServices")
		  {
			var serviceUuids = obj.serviceUuids;
			for (var i = 0; i < serviceUuids.length; i++)
			{
			  var serviceUuid = serviceUuids[i];

			  if (serviceUuid == heartRateServiceUuid)
			  {
				console.log("Finding heart rate characteristics");
				var paramsObj = {"serviceUuid":heartRateServiceUuid, "characteristicUuids":[heartRateMeasurementCharacteristicUuid]};
				bluetoothle.characteristics(characteristicsHeartSuccess, characteristicsHeartError, paramsObj);
				return;
			  }
			}
			console.log("Error: heart rate service not found");
		  }
			else
		  {
			console.log("Unexpected services heart status: " + obj.status);
		  }
		  disconnectDevice();
		}

		servicesHeartError= function(obj)
		{
		  console.log("Services heart error: " + obj.error + " - " + obj.message);
		  disconnectDevice();
		}

		characteristicsHeartSuccess= function(obj)
		{
		  if (obj.status == "discoveredCharacteristics")
		  {
			var characteristicUuids = obj.characteristicUuids;
			for (var i = 0; i < characteristicUuids.length; i++)
			{
			  console.log("Heart characteristics found, now discovering descriptor");
			  var characteristicUuid = characteristicUuids[i];

			  if (characteristicUuid == heartRateMeasurementCharacteristicUuid)
			  {
				var paramsObj = {"serviceUuid":heartRateServiceUuid, "characteristicUuid":heartRateMeasurementCharacteristicUuid};
				bluetoothle.descriptors(descriptorsHeartSuccess, descriptorsHeartError, paramsObj);
				return;
			  }
			}
			console.log("Error: Heart rate measurement characteristic not found.");
		  }
			else
		  {
			console.log("Unexpected characteristics heart status: " + obj.status);
		  }
		  disconnectDevice();
		}

		characteristicsHeartError= function(obj)
		{
		  console.log("Characteristics heart error: " + obj.error + " - " + obj.message);
		  disconnectDevice();
		}

		descriptorsHeartSuccess= function(obj)
		{
		  if (obj.status == "discoveredDescriptors")
		  {
			console.log("Discovered heart descriptors, now discovering battery service");
			var paramsObj = {"serviceUuids":[batteryServiceUuid]};
			bluetoothle.services(servicesBatterySuccess, servicesBatteryError, paramsObj);
		  }
			else
		  {
			console.log("Unexpected descriptors heart status: " + obj.status);
			disconnectDevice();
		  }
		}

		descriptorsHeartError= function(obj)
		{
		  console.log("Descriptors heart error: " + obj.error + " - " + obj.message);
		  disconnectDevice();
		}

		servicesBatterySuccess= function(obj)
		{
		  if (obj.status == "discoveredServices")
		  {
			var serviceUuids = obj.serviceUuids;
			for (var i = 0; i < serviceUuids.length; i++)
			{
			  var serviceUuid = serviceUuids[i];

			  if (serviceUuid == batteryServiceUuid)
			  {
				console.log("Found battery service, now finding characteristic");
				var paramsObj = {"serviceUuid":batteryServiceUuid, "characteristicUuids":[batteryLevelCharacteristicUuid]};
				bluetoothle.characteristics(characteristicsBatterySuccess, characteristicsBatteryError, paramsObj);
				return;
			  }
			}
			console.log("Error: battery service not found");
		  }
			else
		  {
			console.log("Unexpected services battery status: " + obj.status);
		  }
		  disconnectDevice();
		}

		servicesBatteryError= function(obj)
		{
		  console.log("Services battery error: " + obj.error + " - " + obj.message);
		  disconnectDevice();
		}

		characteristicsBatterySuccess= function(obj)
		{
		  if (obj.status == "discoveredCharacteristics")
		  {
			var characteristicUuids = obj.characteristicUuids;
			for (var i = 0; i < characteristicUuids.length; i++)
			{
			  var characteristicUuid = characteristicUuids[i];

			  if (characteristicUuid == batteryLevelCharacteristicUuid)
			  {
				readBatteryLevel();
				return;
			  }
			}
			console.log("Error: Battery characteristic not found.");
		  }
			else
		  {
			console.log("Unexpected characteristics battery status: " + obj.status);
		  }
		  disconnectDevice();
		}

		characteristicsBatteryError= function(obj)
		{
		  console.log("Characteristics battery error: " + obj.error + " - " + obj.message);
		  disconnectDevice();
		}


		readBatteryLevel= function()
		{
		  console.log("Reading battery level");
		  var paramsObj = {"serviceUuid":batteryServiceUuid, "characteristicUuid":batteryLevelCharacteristicUuid};
		  bluetoothle.read(readSuccess, readError, paramsObj);
		}

		readSuccess= function(obj)
		{
			if (obj.status == "read")
			{
				var bytes = bluetoothle.encodedStringToBytes(obj.value);
				console.log("Battery level: " + bytes[0]);

				console.log("Subscribing to heart rate for 5 seconds");
				var paramsObj = {"serviceUuid":heartRateServiceUuid, "characteristicUuid":heartRateMeasurementCharacteristicUuid};
				bluetoothle.subscribe(subscribeSuccess, subscribeError, paramsObj);
				setTimeout(unsubscribeDevice, 5000);
			}
			else
		  {
			console.log("Unexpected read status: " + obj.status);
			disconnectDevice();
		  }
		}

		readError= function(obj)
		{
		  console.log("Read error: " + obj.error + " - " + obj.message);
		  disconnectDevice();
		}

		subscribeSuccess= function(obj)
		{   
			if (obj.status == "subscribedResult")
			{
				//console.log("Subscription data received");

				//Parse array of int32 into uint8
				var bytes = bluetoothle.encodedStringToBytes(obj.value);

				//Check for data
				if (bytes.length == 0)
				{
					console.log("Subscription result had zero length data");
					return;
				}

				//Get the first byte that contains flags
				var flag = bytes[0];

				//Check if u8 or u16 and get heart rate
				var tmp;
				if ((flag & 0x01) == 1)
				{
					var u16bytes = bytes.buffer.slice(1, 3);
					var u16 = new Uint16Array(u16bytes)[0];
					tmp = u16;
				}
				else
				{
					var u8bytes = bytes.buffer.slice(1, 2);
					var u8 = new Uint8Array(u8bytes)[0];
					tmp = u8;
				}
				//console.log("Heart Rate: " + tmp);
            $('#div_hrm').html(tmp);
            hr.bpm = tmp;
            hr.time = new Date();
			}
			else if (obj.status == "subscribed")
			{
				console.log("Subscription started");
			}
			else
		  {
			console.log("Unexpected subscribe status: " + obj.status);
			disconnectDevice();
		  }
		}

		subscribeError= function(obj)
		{
		  console.log("Subscribe error: " + obj.error + " - " + obj.message);
		  disconnectDevice();
		}

		unsubscribeDevice= function()
		{
		  var paramsObj = {"address":address, "serviceUuid":heartRateServiceUuid, "characteristicUuid":heartRateMeasurementCharacteristicUuid};
        console.log("Unsubscribing heart service :" +JSON.stringify(paramsObj));
		  bluetoothle.unsubscribe(unsubscribeSuccess, unsubscribeError, paramsObj);
		}

		unsubscribeSuccess= function(obj)
		{
			if (obj.status == "unsubscribed")
			{
				console.log("Unsubscribed device");

				console.log("Reading client configuration descriptor");
				var paramsObj = {"serviceUuid":heartRateServiceUuid, "characteristicUuid":heartRateMeasurementCharacteristicUuid, "descriptorUuid":clientCharacteristicConfigDescriptorUuid};
				bluetoothle.readDescriptor(readDescriptorSuccess, readDescriptorError, paramsObj);
			}
			else
		  {
			console.log("Unexpected unsubscribe status: " + obj.status);
			disconnectDevice();
		  }
		}

		unsubscribeError= function(obj)
		{
		  console.log("Unsubscribe error: " + obj.error + " - " + obj.message);
		  disconnectDevice();
		}

		readDescriptorSuccess= function(obj)
		{
			if (obj.status == "readDescriptor")
			{
				var bytes = bluetoothle.encodedStringToBytes(obj.value);
				var u16Bytes = new Uint16Array(bytes.buffer);
				console.log("Read descriptor value: " + u16Bytes[0]);
				disconnectDevice();
			}
			else
		  {
			console.log("Unexpected read descriptor status: " + obj.status);
			disconnectDevice();
		  }
		}

		readDescriptorError= function(obj)
		{
		  console.log("Read Descriptor error: " + obj.error + " - " + obj.message);
		  disconnectDevice();
		}

		disconnectDevice= function()
		{
         var paramsObj = {"address":address};
         bluetoothle.disconnect(disconnectSuccess, disconnectError, paramsObj);
		}

		disconnectSuccess= function(obj)
		{
			if (obj.status == "disconnected")
			{
				console.log("Disconnect device");
				closeDevice();
			}
			else if (obj.status == "disconnecting")
			{
				console.log("Disconnecting device");
			}
			else
		  {
			console.log("Unexpected disconnect status: " + obj.status);
		  }
		}

		disconnectError= function(obj)
		{
		  console.log("Disconnect error: " + obj.error + " - " + obj.message);
		}

		closeDevice= function()
		{
         var paramsObj = {"address":address};
		  bluetoothle.close(closeSuccess, closeError, paramsObj);
		}

		closeSuccess= function(obj)
		{
			if (obj.status == "closed")
			{
				console.log("Closed device");
			}
			else
		  {
			console.log("Unexpected close status: " + obj.status);
		  }
		}

		closeError= function(obj)
		{
		  console.log("Close Error : " + JSON.stringify(obj));
		}	
	})
	
	
	.service('ConfigurationService', function(APP){
	
	});